package com.hup.minicontroller.client.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import lombok.Setter;

/**
 * 展示投屏图像和处理触摸事件
 *
 * @author hugan
 * @date 2021/5/6
 */
public class ScreenView extends View {
    private static final String TAG = ScreenView.class.getSimpleName();

    /**
     * 当前view的尺寸
     */
    private int width, height;
    /**
     * 画布相关属性
     */
    private Rect rectImage, rectDraw;
    private Paint ptImage;

    /**
     * 图像是否平铺界面
     */
    private boolean isFull = false;
    private Bitmap screenImage;
    @Setter
    private TouchEventCallback touchEventCallback;

    public ScreenView(Context context) {
        this(context, null);
    }

    public ScreenView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScreenView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ScreenView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }

    @SuppressWarnings("unused")
    private void init(Context context, AttributeSet attrs) {
        ptImage = new Paint();
        ptImage.setFilterBitmap(true);
        ptImage.setDither(true);
        rectImage = new Rect();
        rectDraw = new Rect();
        setOnTouchListener(new MyTouchListener());
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldW, int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        //Log.i(TAG, "onSizeChanged: " + w + "," + h + ", old=" + oldW + "," + oldH);
        width = w;
        height = h;
        updateRect();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (screenImage != null) canvas.drawBitmap(screenImage, rectImage, rectDraw, ptImage);
    }

    private void updateRect() {
        if (screenImage == null || width * height == 0) return;
        //图像区域
        int imgWidth = screenImage.getWidth();
        int imgHeight = screenImage.getHeight();
        rectImage.set(0, 0, imgWidth, imgHeight);
        //绘制区域
        if (isFull) {
            //平铺图像
            rectDraw.set(0, 0, width, height);
            return;
        }
        float scaleView = ((float) width) / height;
        float scaleImg = ((float) imgWidth) / imgHeight;
        if (scaleView == scaleImg) {
            //刚好铺满.一般不会发生
            rectDraw.set(0, 0, width, height);
        } else if (scaleView > scaleImg) {
//            Log.i(TAG, "updateRect: 左右空白");
            imgWidth = (int) (height * scaleImg);//图像新宽度
            int left = (width - imgWidth) / 2;
            rectDraw.set(left, 0, left + imgWidth, height);//不深究要不要加减1 ???
        } else {
//            Log.i(TAG, "updateRect: 上下空白");
            imgHeight = (int) (width / scaleImg);
            int top = (height - imgHeight) / 2;
            rectDraw.set(0, top, width, top + imgHeight);
        }
    }

    public void setFull(boolean b) {
        isFull = b;
        updateRect();
        invalidate();
    }

    public void setScreenImage(Bitmap input) {
        if (screenImage != null) {
            Bitmap temp = screenImage;
            //不能先recycled再赋值,防止draw时异常
            screenImage = input;
            temp.recycle();
        } else {
            screenImage = input;
        }
        updateRect();
        invalidate();
    }

    public void switchVisible(boolean isShow) {
        setVisibility(isShow ? VISIBLE : GONE);
        if (!isShow && screenImage != null) {
            Bitmap temp = screenImage;
            screenImage = null;
            temp.recycle();
        }
    }

    /**
     * 实现投屏触摸功能
     */
    private class MyTouchListener implements OnTouchListener {
        private int lastX, lastY;
        /**
         * 是否为要处理的触摸事件;
         * 按下时,不在图像区域,一律过滤
         */
        private boolean touching = false;

        @Override
        @SuppressLint("ClickableViewAccessibility")
        public boolean onTouch(View v, MotionEvent e) {
            if (touchEventCallback == null) return true;
            int x = (int) e.getX();
            int y = (int) e.getY();
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touching = rectDraw.contains(x, y);
                    if (!touching) return true;
//                    Log.i(TAG, "onTouch: ACTION_DOWN");
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (!touching) return true;
                    if (Math.abs(lastX - x) < 2 && Math.abs(lastY - y) < 2) return true;//过滤微小移动
//                    Log.i(TAG, "onTouch: ACTION_MOVE");
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    if (!touching) return true;
//                    Log.i(TAG, "onTouch: ACTION_UP");
                    touching = false;
                    break;
            }
            lastX = x;
            lastY = y;
            handleEvent(e, x, y);
            return true;
        }

        private void handleEvent(MotionEvent e, int x, int y) {
            float xPercent = (x - rectDraw.left + 0f) / rectDraw.width();
            if (xPercent < 0) xPercent = 0;
            else if (xPercent > 1) xPercent = 1;
            float yPercent = (y - rectDraw.top + 0f) / rectDraw.height();
            if (yPercent < 0) yPercent = 0;
            else if (yPercent > 1) yPercent = 1;
            touchEventCallback.handleEvent(e.getAction(), xPercent, yPercent);
        }
    }

    /**
     * 触摸事件回调
     */
    public interface TouchEventCallback {
        /**
         * @param action {@link MotionEvent#getAction()}
         * @param xPercent 坐标位置百分比
         * @param yPercent 坐标位置百分比
         */
        void handleEvent(int action, float xPercent, float yPercent);
    }
}
